import express from 'express';
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
import { prisma } from '../app';
import { asyncHandler, createError } from '../middleware/errorHandler';
import { validateRegisterInput, validateLoginInput } from '../middleware/validation';
import { authenticateToken, AuthRequest } from '../middleware/auth';

const router = express.Router();

// Register
router.post('/register', validateRegisterInput, asyncHandler(async (req, res) => {
  const { username, email, password } = req.body;

  // Check if user already exists
  const existingUser = await prisma.user.findFirst({
    where: {
      OR: [
        { email },
        { username }
      ]
    }
  });

  if (existingUser) {
    if (existingUser.email === email) {
      throw createError('Email already registered', 409);
    }
    if (existingUser.username === username) {
      throw createError('Username already taken', 409);
    }
  }

  // Hash password
  const saltRounds = 12;
  const passwordHash = await bcrypt.hash(password, saltRounds);

  // Create user
  const user = await prisma.user.create({
    data: {
      username,
      email,
      passwordHash
    },
    select: {
      id: true,
      username: true,
      email: true,
      createdAt: true
    }
  });

  // Create default todo list
  await prisma.todoList.create({
    data: {
      name: '我的任务',
      userId: user.id
    }
  });

  // Generate JWT token
  const jwtSecret = process.env.JWT_SECRET;
  if (!jwtSecret) {
    throw createError('JWT secret not configured', 500);
  }

  const token = jwt.sign(
    { userId: user.id },
    jwtSecret,
    { expiresIn: '7d' }
  );

  res.status(201).json({
    success: true,
    message: 'User registered successfully',
    data: {
      user,
      accessToken: token
    }
  });
}));

// Login
router.post('/login', validateLoginInput, asyncHandler(async (req, res) => {
  const { email, password } = req.body;

  // Find user by email
  const user = await prisma.user.findUnique({
    where: { email }
  });

  if (!user) {
    throw createError('Invalid email or password', 401);
  }

  // Check password
  const isPasswordValid = await bcrypt.compare(password, user.passwordHash);
  if (!isPasswordValid) {
    throw createError('Invalid email or password', 401);
  }

  // Generate JWT token
  const jwtSecret = process.env.JWT_SECRET;
  if (!jwtSecret) {
    throw createError('JWT secret not configured', 500);
  }

  const token = jwt.sign(
    { userId: user.id },
    jwtSecret,
    { expiresIn: '7d' }
  );

  // Record login activity
  const today = new Date();
  today.setHours(0, 0, 0, 0);

  await prisma.userActivity.upsert({
    where: {
      userId_date: {
        userId: user.id,
        date: today
      }
    },
    update: {
      count: {
        increment: 1
      }
    },
    create: {
      userId: user.id,
      date: today,
      count: 1
    }
  });

  res.json({
    success: true,
    message: 'Login successful',
    data: {
      user: {
        id: user.id,
        username: user.username,
        email: user.email,
        avatarUrl: user.avatarUrl,
        createdAt: user.createdAt
      },
      accessToken: token
    }
  });
}));

// Get current user profile
router.get('/profile', authenticateToken, asyncHandler(async (req: AuthRequest, res) => {
  const user = await prisma.user.findUnique({
    where: { id: req.user!.id },
    select: {
      id: true,
      username: true,
      email: true,
      avatarUrl: true,
      createdAt: true
    }
  });

  if (!user) {
    throw createError('User not found', 404);
  }

  res.json({
    success: true,
    data: { user }
  });
}));

// Update user profile
router.put('/profile', authenticateToken, asyncHandler(async (req: AuthRequest, res) => {
  const { username, avatarUrl } = req.body;
  const userId = req.user!.id;

  const updateData: any = {};
  
  if (username) {
    if (username.length < 3 || username.length > 20) {
      throw createError('Username must be between 3 and 20 characters', 400);
    }
    
    // Check if username is already taken by another user
    const existingUser = await prisma.user.findFirst({
      where: {
        username,
        NOT: { id: userId }
      }
    });
    
    if (existingUser) {
      throw createError('Username already taken', 409);
    }
    
    updateData.username = username;
  }
  
  if (avatarUrl !== undefined) {
    updateData.avatarUrl = avatarUrl;
  }

  const user = await prisma.user.update({
    where: { id: userId },
    data: updateData,
    select: {
      id: true,
      username: true,
      email: true,
      avatarUrl: true,
      createdAt: true
    }
  });

  res.json({
    success: true,
    message: 'Profile updated successfully',
    data: { user }
  });
}));

// Verify token
router.get('/verify', authenticateToken, asyncHandler(async (req: AuthRequest, res) => {
  res.json({
    success: true,
    message: 'Token is valid',
    data: {
      user: req.user
    }
  });
}));

export default router;